/*
 * protocol_client.c
 *
 *  Created on: May 4, 2011
 *      Author: onteria_
 */
#include <stdint.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/socket.h>
#include <stdio.h>

#include <miko/defines.h>
#include <miko/miko.h>
#include <miko/socket.h>
#include <miko/protocol.h>

/**
 * Function: process_miko_data
 *
 * A function to read a miko structure from a socket, with some error handling included
 *
 * Parameters:
 *
 *      socket_descriptor - The file descriptor of the client socket
 *      miko - A pointer to the Miko structure to populate
 *      timeout - The timeout in seconds to wait
 *
 * Returns:
 *
 *      MIKO_SUCCESS or a MIKO_ error related to socket communication or invalid data
 */
int send_miko_data(int socket_descriptor, struct Miko * miko) {
	uint32_t length;
	long bytes_sent;

    /* Convert to network byte order to help with endian-ness issues */
    length = (sizeof(UChar) * MIKO_FIRST_NAME_MAX) + (sizeof(UChar) * MIKO_LAST_NAME_MAX) + (sizeof(UChar) * MIKO_SHRINE_NAME_MAX);
    length = htonl(length);

    /* Our protocol is a 32 bit integer indicating the message length, followed by */
    bytes_sent = send(socket_descriptor, &length, sizeof(uint32_t), 0);
    if(bytes_sent < 0) {
        perror("Send error: ");
        return MIKO_SEND_FAILED;
    }

    bytes_sent = send(socket_descriptor, miko->firstName, sizeof(UChar) * MIKO_FIRST_NAME_MAX, 0);
    if(bytes_sent < 0) {
        perror("Send error: ");
        return MIKO_SEND_FAILED;
    }

    bytes_sent = send(socket_descriptor, miko->lastName, sizeof(UChar) * MIKO_LAST_NAME_MAX, 0);
    if(bytes_sent < 0) {
        perror("Send error: ");
        return MIKO_SEND_FAILED;
    }

    bytes_sent = send(socket_descriptor, miko->shrine, sizeof(UChar) * MIKO_SHRINE_NAME_MAX, 0);
    if(bytes_sent < 0) {
        perror("Send error: ");
        return MIKO_SEND_FAILED;
    }

    return bytes_sent;
}

/**
 * Function: miko_send_response
 *
 * Write a server response to the socket
 *
 * Parameters:
 *
 *      socket_descriptor - The file descriptor of the socket
 *      response_code - The response code to retrieve
 *      message - A human readable message describing the response
 *
 * Returns:
 *
 *      MIKO_SUCCESS on success, MIKO_SEND_FAILED or MIKO_MSG_TOO_LONG on failure
 */
int miko_read_server_response(int socket_descriptor, int timeout, int * response_code, char * message) {
	uint32_t length;
	long bytes_read;

    bytes_read = miko_read_socket(socket_descriptor, &length, sizeof(uint32_t), timeout);
    if(bytes_read < 0) {
    	return bytes_read;
    }

    if(length != sizeof(int) + (sizeof(char) * MIKO_MSG_LENGTH)) {
    	return MIKO_DATA_CHECK_FAILURE;
    }

    bytes_read = miko_read_socket(socket_descriptor, response_code, sizeof(int), timeout);
    if(bytes_read < 0) {
    	return bytes_read;
    }

    bytes_read = miko_read_socket(socket_descriptor, message, length - sizeof(int), timeout);
    if(bytes_read < 0) {
    	return bytes_read;
    }

    return bytes_read;
}
